﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using RuoVea.EventBus;
using RuoVea.ExApp;
using RuoVea.ExDto;
using RuoVea.ExEnum;
using RuoVea.ExEvenBus;
using RuoVea.ExSugar.Entity;
using RuoVea.ExSugar.Option;
using RuoVea.ExUtil;
using SqlSugar;
using System;
using System.Linq;

namespace RuoVea.ExSugar.Util;

/// <summary>
/// sqlsugar Aop
/// </summary>
public class SugarAopUtil
{
    /// <summary>
    /// sql扩展处理
    /// </summary>
    /// <param name="sql"></param>
    /// <param name="pars"></param>
    public static async void OnLogExecuting(string sql, SugarParameter[] pars)
    {
        if (sql.StartsWith("SELECT")) { Console.ForegroundColor = ConsoleColor.Green; }
        if (sql.StartsWith("UPDATE") || sql.StartsWith("INSERT")) { Console.ForegroundColor = ConsoleColor.White; }
        if (sql.StartsWith("DELETE")) { Console.ForegroundColor = ConsoleColor.Blue; }
        string outSql = "1. SQL调试: >> 操作时间: " + DateTime.Now + " \r\n" + SqlProfiler.ParameterFormat(sql, pars);
        ConsoleHelper.WriteWarningLine(outSql);
        try
        {
            IEventPublisher _eventPublisher = App.GetRequiredService<IEventPublisher>();
            await _eventPublisher.PublishAsync(new ChannelEventSource("LogEvent:LogExecuting", outSql));
        }
        catch { }
    }

    /// <summary>
    /// 配置Aop
    /// </summary>
    /// <param name="db"></param>
    /// <param name="config"></param>
    /// <param name="whenUser">whenUser 默认为false true的时候 当有用户cretor的时候将及时过滤</param>
    public static async void SetDbAop(SqlSugarScopeProvider db, DbConnectionConfig config, bool whenUser = false)
    {
        //var config = db.CurrentConnectionConfig;

        // 设置超时时间
        db.Ado.CommandTimeOut = 30;
        // 打印SQL语句
        db.Aop.OnLogExecuting = async (sql, pars) => OnLogExecuting(sql, pars);
        // 数据审计
        db.Aop.DataExecuting = async (oldValue, entityInfo) =>
        {
            if (entityInfo.OperationType == DataFilterType.InsertByObject)
            {
                // 主键(long类型)且没有值的-赋值雪花Id
                if (entityInfo.EntityColumnInfo.IsPrimarykey && entityInfo.EntityColumnInfo.PropertyInfo.PropertyType == typeof(long))
                {
                    var id = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
                    if (id == null || (long)id == 0)
                        entityInfo.SetValue(ExIdGen.IdGenerator.Id);
                }
                if (entityInfo.PropertyName == "CreateTime")
                {
                    var createTime = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
                    if (createTime == null)
                    {
                        entityInfo.SetValue(DateTime.Now);
                    }
                }
                if (App.User != null)
                {
                    if (entityInfo.PropertyName == "TenantId")
                    {
                        var tenantId = ((dynamic)entityInfo.EntityValue).TenantId;
                        if (tenantId == null || tenantId == 0)
                            entityInfo.SetValue(App.User.FindFirst(ClaimConst.TENANT_ID)?.Value);
                    }
                    if (entityInfo.PropertyName == "Creator")
                    {
                        var creator = ((dynamic)entityInfo.EntityValue).Creator;
                        if (creator == 0 || creator == null)
                            entityInfo.SetValue(App.User.FindFirst(ClaimConst.CLAINM_USERID)?.Value);
                    }

                    if (entityInfo.PropertyName == "CreateOrgId")
                    {
                        var createOrgId = ((dynamic)entityInfo.EntityValue).CreateOrgId;
                        if (createOrgId == 0 || createOrgId == null)
                            entityInfo.SetValue(App.User.FindFirst(ClaimConst.OrgId)?.Value);
                    }
                }
            }
            if (entityInfo.OperationType == DataFilterType.UpdateByObject)
            {
                if (entityInfo.PropertyName == "ModifyTime")
                {
                    var createTime = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue);
                    if (createTime == null)
                    {
                        entityInfo.SetValue(DateTime.Now);
                    }
                }
                if (App.User != null)
                {
                    if (entityInfo.PropertyName == "Modifier" && App.User?.FindFirst(ClaimConst.CLAINM_USERID) != null)
                    {
                        var modifier = ((dynamic)entityInfo.EntityValue).Modifier;
                        if (modifier == 0 || modifier == null)
                        {
                            entityInfo.SetValue(App.User?.FindFirst(ClaimConst.CLAINM_USERID)?.Value);
                        }
                    }
                }
            }
        };

        db.Aop.OnError = async (ex) =>
        {
            if (ex.Parametres == null) return;
            var originColor = Console.ForegroundColor;
            Console.ForegroundColor = ConsoleColor.DarkRed;
            var pars = db.Utilities.SerializeObject(((SugarParameter[])ex.Parametres).ToDictionary(it => it.ParameterName, it => it.Value));
            Console.WriteLine("【" + DateTime.Now + "——错误SQL】\r\n" + UtilMethods.GetSqlString(config.DbType, ex.Sql, (SugarParameter[])ex.Parametres) + "\r\n");
            Console.ForegroundColor = originColor;
            try
            {
                IEventPublisher _eventPublisher = App.GetRequiredService<IEventPublisher>();
                await _eventPublisher.PublishAsync(new ChannelEventSource("LogEvent:SqlSugarError", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}"));
                //Emit.Publish("LogEvent:SqlSugarError", $"{ex.Message}{Environment.NewLine}{ex.Sql}{pars}{Environment.NewLine}"); 
            }
            catch { }
        };


        if (config.EnableDiffLog)
        {
            db.Aop.OnDiffLogEvent = async u =>
            {
                //ConsoleHelper.WriteWarningLine("11111111111111");
                var logDiff = new
                {
                    // 操作后记录（字段描述、列名、值、表名、表描述）
                    AfterData = u.AfterData.Json2Str(),
                    // 操作前记录（字段描述、列名、值、表名、表描述）
                    BeforeData = u.BeforeData.Json2Str(),
                    // 传进来的对象
                    BusinessData = u.BusinessData.Json2Str(),
                    // 枚举（insert、update、delete）
                    DiffType = u.DiffType.ToString(),
                    Sql = UtilMethods.GetSqlString(config == null ? DbType.Sqlite : config.DbType, u.Sql, u.Parameters),
                    Parameters = u.Parameters.Json2Str(),
                    Elapsed = u.Time == null ? 0 : (long)u.Time.Value.TotalMilliseconds
                };
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(DateTime.Now + $"\r\n*****差异日志开始*****\r\n{Environment.NewLine}{logDiff.Json2Str()}{Environment.NewLine}*****差异日志结束*****\r\n");

                try
                {
                    IEventPublisher _eventPublisher = App.GetRequiredService<IEventPublisher>();
                    await _eventPublisher.PublishAsync(new ChannelEventSource("LogEvent:LogExecuting", logDiff.Json2Str()));
                    //Emit.Publish("LogEvent:DbDiffLog", logDiff.Json2Str()); 
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Failed to emit {ex.Message}");
                    var t = ex;
                }
            };
        }

        // 超管时排除各种过滤器
        if (App.User?.FindFirst(ClaimConst.CLAINM_SUPERADMIN)?.Value == ((int)AdminType.SuperAdmin).ToString())
            return;

        // 配置实体假删除过滤器
        db.QueryFilter.AddTableFilter<IDeletedFilter>(u => u.IsDeleted == IsDelete.N);

        if (whenUser)
        {
            // 配置租户过滤器
            var userId = App.User?.FindFirst(ClaimConst.CLAINM_USERID)?.Value;
            if (!string.IsNullOrWhiteSpace(userId))
            {
                db.QueryFilter.AddTableFilter<EntityBase>(u => u.Creator == long.Parse(userId));
                db.QueryFilter.AddTableFilter<ICreatorFilter>(u => u.Creator == long.Parse(userId));
            }
        }
        // 配置租户过滤器
        var tenantId = App.User?.FindFirst(ClaimConst.TENANT_ID)?.Value;
        if (!string.IsNullOrWhiteSpace(tenantId))
            db.QueryFilter.AddTableFilter<ITenantIdFilter>(u => u.TenantId == long.Parse(tenantId));

        string orgId = App.User?.FindFirst(ClaimConst.OrgId)?.Value;
        if (orgId.NotNullOrWhiteSpace()&& orgId != "0")
        {
            string[] orgIds = orgId.Split(",");
            if (orgIds.Count() > 0)
            {
                SqlSugarFilter.SetOrgEntityFilter(db, orgIds.ToList());
            }
        }
        //// 配置用户机构（数据范围）过滤器
        //SqlSugarFilter.SetOrgEntityFilter(db);
        //// 配置自定义过滤器
        //SqlSugarFilter.SetCustomEntityFilter(db);
    }
}
